
#ifndef RENDERIZER_H_
#define RENDERIZER_H_

#include "SDL.h"
#include "SDL_thread.h"
#include "SDL_ttf.h"
#include "map.hpp"
#include "mapElement.hpp"
#include "mapStreet.hpp"
#include "mapIntersection.hpp"
#include "mapCar.hpp"
#include "../logger/logger.hpp"
#include "../main/administrator.hpp"
#include "messageAdministrator.hpp"

#define PI 3.1415161718

class Renderizer{

private:
	Administrator *admin;
	Logger	*logger;
	Map		*map;
	double	zoomIndex;
	int		viewPortX;
	int		viewPortY;
	int		ResolutionX;
	int		ResolutionY;
	int		mpp; /*Metros por pixel*/
	int		bpp;

	int		mapDisplacementX;
	int		mapDisplacementY;
	int		displacementConstant;
	int		middlePointConstant;
	int		vMutex;

	//The protective mutex
	SDL_mutex *bufferLock;

	//The conditions
	SDL_cond *canProduce;
	SDL_cond *canConsume;

	MessageAdministrator ma;

	SDL_Surface	*mapSurface;
	SDL_Surface	*mapResizedSurface;
	SDL_Surface *minimunPathSurface;
	SDL_Surface *minimunResizedPathSurface;
	SDL_Surface	*objectsSurface;
	SDL_Surface	*background;
	SDL_Surface	*screen;
	SDL_Surface	*inputSurface;
	SDL_Surface	*directiveSurface;
	MapCar		*car;
	SDL_Surface *carSurface;
	SDL_Surface *carResizedSurface;

	SDL_Surface *message;
	SDL_Surface *message2;
	SDL_Surface *message3;
	SDL_Surface *messageBox;
	TTF_Font *font;
	SDL_Color redColor;
	SDL_Color greenColor;

	int getMiddlePointConstant();
	void setMiddlePointConstant(int mpc);
	void generateStreet(int module, double alpha, SDL_Rect *position, SDL_Surface *streetImg, SDL_Surface *destination);
	void generateStreetMP(int module, double alpha, SDL_Rect *position, SDL_Surface *destination, int iniMPPercent, int endMPPercent);
	void calculateObjectPosition(SDL_Rect *origin, SDL_Rect *destiny, SDL_Rect *position, SDL_Rect *image, double percent,double alpha, bool parity,bool grows);
	bool getParity(int deltaHeight, int objHeight);
	void setSurfaceTransparent(SDL_Surface *surface);

	Uint32 getPixel(int x, int y,SDL_Surface* source);
	void putPixel(int x, int y, Uint32 pixel,SDL_Surface *destination);

	void rotate(int x, int y, double alpha, SDL_Rect *offset);
	void rotateImage(double alpha, SDL_Surface *toRotate, SDL_Surface *rotated);

public:
	Renderizer(){}

	void create(Map *m, Logger *log, Administrator *admin);

	virtual ~Renderizer();
	int Hilo();
	
	int renderApplication(std::string path);

	int renderInput(SDL_Surface *screen, std::string path);

	int renderDirectives(SDL_Surface *screen);

	SDL_Surface* generateMap();
	int renderMap(std::string path);
	int renderMap(std::string path,bool withMP);
	void renderMinimunPath(SDL_Surface *destination, bool exists);
	void renderStreetsAndIntersections(SDL_Surface *destination);
	void renderMapIntersection(MapIntersection *mi, SDL_Surface *destination, bool withMP);
	void renderMapStreet(MapStreet *ms, SDL_Surface *destination, bool withMP);
	void renderMapObjects(SDL_Surface *destination);
	void renderMapObject(MapObject *mo, SDL_Surface *destination);
	void renderDirection(MapStreet *ms, SDL_Surface *destination);
	void refreshMap(SDL_Surface *source, SDL_Surface *destination);
	SDL_Surface * resize(SDL_Surface *screen);	

	SDL_Surface* getSurface(MapElement *me);
	void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination );

	double getZoomIndex();
	int getViewPortX();
	int getViewPortY();
	int getResolutionX();
	int getResolutionY();
	int getMpp();
	int getBpp();

	bool quit;

	void setZoomIndex(double index);
	void setViewPortX(int w);
	void setViewPortY(int h);
	void setResolutionX(int w);
	void setResolutionY(int h);
	void setBpp(int b);
	void setMpp(int m);

	int getMapElementPositionX(MapElement *me);
	int getMapElementPositionX(int x);
	int getMapElementPositionY(MapElement *me);
	int getMapElementPositionY(int y);

	int getMapElementDisplacementX();
	int getMapElementDisplacementY();

	int getDisplacementConstant();
	void setDisplacementConstant(int c);

	int getMapDisplacementX();
	int getMapDisplacementY();

	void setMapDisplacementX(int x);
	void setMapDisplacementY(int y);

	SDL_Surface * moveZoomIn(SDL_Surface *map);
	SDL_Surface * moveZoomOut(SDL_Surface *map);
	void moveMapUp(SDL_Surface *map);
	void moveMapDown();
	void moveMapLeft(SDL_Surface *map);
	void moveMapRight();

	MapIntersection* getMapIntersection(int x, int y);
	bool isOnCorrectDirection(MapElement *me);

	MapStreet* getMapStreet(int x, int y);
	MapStreet* getMapStreet(int x, int y, BifurcationOption direction);
	MapStreet* getMapStreetSentido(int x, int y, BifurcationOption direction);
	void initCar(std::string streetName,MapCar *mc);
	bool isInsideVerticalRange(MapStreet* ms, int y);
	bool isInsideHorizontalRange(MapStreet* ms, int x);

	bool isOnIntersection(MapElement *me);
	bool isOnStreet(MapElement *me, MapStreet *ms);
	bool isOnMapElement(MapElement *meSubject, MapElement *me);

	void fillSurfaceWithKeyColor(SDL_Surface *surface);
	void fillSurfaceWithBackGroundColor(SDL_Surface *surface);

	void setMessageAdministrator(MapStreet *ms, MapCar *mc);
};

#endif /* RENDERIZER_H_ */